package com.ruoyi.order.service.impl;

import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.customer.domain.*;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.MyUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.customer.service.*;
import com.ruoyi.employee.domain.EmployeeFinance;
import com.ruoyi.employee.domain.EmployeeUser;
import com.ruoyi.employee.service.IEmployeeFinanceService;
import com.ruoyi.employee.service.IEmployeeStaticService;
import com.ruoyi.employee.service.IEmployeeUserService;
import com.ruoyi.market.domain.ConfigOrder;
import com.ruoyi.market.domain.Coupon;
import com.ruoyi.market.domain.Level;
import com.ruoyi.market.service.IConfigOrderService;
import com.ruoyi.market.service.ICouponService;
import com.ruoyi.market.service.ILevelService;
import com.ruoyi.order.domain.OrderGoods;
import com.ruoyi.order.mapper.OrderGoodsMapper;
import com.ruoyi.order.service.IOrderGoodsService;
import com.ruoyi.thirdpart.service.IBizWechatPayService;
import com.ruoyi.thirdpart.service.IWxOAuthchatService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.Validator;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

/**
 * 商品订单 业务层处理
 * 
 * @author ruoyi
 */
@Service
public class OrderGoodsServiceImpl implements IOrderGoodsService
{
    @Autowired
    private OrderGoodsMapper orderGoodsMapper;

    @Autowired
    private ICustomerUserService customerUserService;

    @Autowired
    private ICustomerStaticService customerStaticService;

    @Autowired
    private ICustomerCouponService customerCouponService;

    @Autowired
    private ICouponService couponService;

    @Autowired
    private IEmployeeUserService employeeUserService;

    @Autowired
    private ICustomerFinanceService customerFinanceService;

    @Autowired
    private IEmployeeFinanceService employeeFinanceService;

    @Autowired
    private IEmployeeStaticService employeeStaticService;

    @Autowired
    private ILevelService levelService;

    @Autowired
    private ICustomerDistributionService customerDistributionService;

    @Autowired
    private IBizWechatPayService bizWechatPayService;

    @Autowired
    private IWxOAuthchatService wxOAuthchatService;

    @Autowired
    private IConfigOrderService configOrderService;

    @Autowired
    protected Validator validator;

    /**
     * 根据条件分页查询商品订单列表
     * 
     * @param orderGoods 商品订单信息
     * @return 商品订单信息集合信息
     */
    @Override
    @DataScope(orderAlias = "o", userAlias = "u")
    public List<OrderGoods> selectOrderGoodsList(OrderGoods orderGoods)
    {
        return orderGoodsMapper.selectOrderGoodsList(orderGoods);
    }

    /**
     * 通过商品订单编号查询商品订单
     * 
     * @param orderNo 商品订单编号
     * @return 商品订单对象信息
     */
    @Override
    public OrderGoods selectOrderGoodsByOrderNo(String orderNo)
    {
        return orderGoodsMapper.selectOrderGoodsByOrderNo(orderNo);
    }

    /**
     * 查询商品订单总数汇总 - 条数
     *
     * @param orderGoods 商品订单信息
     * @return 商品订单对象信息
     */
    @Override
    public int selectOrderGoodsCountTotal(OrderGoods orderGoods)
    {
        return orderGoodsMapper.selectOrderGoodsCountTotal(orderGoods);
    }

    /**
     * 查询商品订单每日新增总数 - 条数
     *
     * @param orderGoods 商品订单信息
     * @return 商品订单对象信息
     */
    @Override
    public List<Map<String, Object>> selectOrderGoodsCountDaily(OrderGoods orderGoods)
    {
        return orderGoodsMapper.selectOrderGoodsCountDaily(orderGoods);
    }

    /**
     * 查询商品订单总数汇总 - 金额
     *
     * @param orderGoods 商品订单信息
     * @return 商品订单对象信息
     */
    @Override
    public BigDecimal selectOrderGoodsAmountTotal(OrderGoods orderGoods)
    {
        return orderGoodsMapper.selectOrderGoodsAmountTotal(orderGoods);
    }

    /**
     * 查询商品订单每日新增总数 - 金额
     *
     * @param orderGoods 商品订单信息
     * @return 商品订单对象信息
     */
    @Override
    public List<Map<String, Object>> selectOrderGoodsAmountDaily(OrderGoods orderGoods)
    {
        return orderGoodsMapper.selectOrderGoodsAmountDaily(orderGoods);
    }

    /**
     * 查询店员在待服务和服务中的订单数量
     *
     * @param employeeUserId 店员Id
     * @return 结果
     */
    @Override
    public Integer countOrderGoodsByEmployeeId(Long employeeUserId)
    {
        return orderGoodsMapper.countOrderGoodsByEmployeeId(employeeUserId);
    }

    /**
     * 新增保存商品订单信息
     * 
     * @param orderGoods 商品订单信息
     * @return 结果
     */
    @Override
    @Transactional
    public OrderGoods insertOrderGoods(OrderGoods orderGoods)
    {
        // 指定店员的单 - 查询客户是否可以接单
        if(StringUtils.isNotNull(orderGoods.getEmployeeUserId())){
            // 新增商品订单信息
            EmployeeUser e = employeeUserService.selectUserById(orderGoods.getEmployeeUserId());
            // 被禁用或者下线都不能接单
            if (!e.getActive().equals(UserConstants.NORMAL) || e.getStatus().equals(UserConstants.OFFLINE))
            {
                throw new ServiceException("当前店员不在线，无法接单！");
            }
            orderGoods.setAcceptType(UserConstants.ZERO);
            orderGoods.setIsAccept(UserConstants.YES);
        }else if(StringUtils.isNotNull(orderGoods.getGoodsId())){
            // 有商品ID，是盲盒订单
            orderGoods.setAcceptType(UserConstants.ONE);
            orderGoods.setIsAccept(UserConstants.NO);
        }else if(StringUtils.isNotNull(orderGoods.getGoodsId())){
            // 无商品ID，是体验订单
            int count = orderGoodsMapper.checkCustomerExperienceOrder(orderGoods.getOrderUserId());
            if(count > 0){
                throw new ServiceException("下单失败，仅限首次购买体验单的用户！");
            }
            // 先查询是否可以下单
            orderGoods.setAcceptType(UserConstants.TWO);
            orderGoods.setIsAccept(UserConstants.NO);
        }

        // 这个顺序不能乱，否则底下无法获取值
        Long userId = SecurityUtils.getUserId();
        CustomerUser customerUser = customerUserService.selectUserById(userId);
        String orderNo = MyUtils.getOrderNoByTimeAndId(userId);
        orderGoods.setAppId(customerUser.getAppId());
        orderGoods.setShopId(customerUser.getShopId());
        orderGoods.setOrderNo(orderNo);
        orderGoods.setOrderUserId(userId);

        // 使用卡券
        if(StringUtils.isNotNull(orderGoods.getCustomerCouponId())){
            CustomerCoupon customerCoupon = customerCouponService.selectCustomerCouponById(orderGoods.getCustomerCouponId());
            if(StringUtils.isNotNull(customerCoupon) && customerCoupon.getStatus().equals(UserConstants.ZERO)){
                // 更新客户卡券使用状态 客户卡券状态（0待使用 1已使用 2已过期）
                customerCoupon.setStatus(UserConstants.ONE);
                customerCoupon.setGoodsId(orderGoods.getGoodsId());
                customerCoupon.setUseTime(new Date());
                customerCouponService.updateCustomerCoupon(customerCoupon);

                // 更新卡券使用人数
                Coupon coupon = couponService.selectCouponById(customerCoupon.getCouponId());
                coupon.setCouponUseCount(coupon.getCouponUseCount() + 1);
                couponService.updateCoupon(coupon);

                orderGoods.setCouponId(customerCoupon.getCouponId());
            }
        }

        ConfigOrder configOrder = configOrderService.selectConfigOrderByShopId(orderGoods.getShopId());
        // 设置时间提醒
        if(configOrder != null){
            // 创建一个Calendar实例并设置为当前时间
            Calendar calendar_1 = Calendar.getInstance();
            Calendar calendar_2 = Calendar.getInstance();
            // 订单超时取消时间
            if(configOrder.getStatusOvertimeCancel() > 0){
                // 将分钟数加到当前时间上
                calendar_1.add(Calendar.MINUTE, configOrder.getStatusOvertimeCancel());
                orderGoods.setOvertimeCancelTime(calendar_1.getTime()); // 取消时间
            }
            // 订单超时提醒时间
            if(configOrder.getStatusOvertimeNotice() > 0){
                // 将分钟数加到当前时间上
                calendar_2.add(Calendar.MINUTE, configOrder.getStatusOvertimeNotice());
                orderGoods.setOvertimeNoticeTime(calendar_2.getTime()); // 取消时间
            }
        }

        // 支付
        if(orderGoods.getPayType().equals(UserConstants.PAY_TYPE_BALANCE) && StringUtils.isNotNull(userId)){
            // 使用余额支付
            if(customerUser.getBalance().compareTo(orderGoods.getActualAmount()) == -1){
                throw new ServiceException("客户下单失败：可用余额不足");
            }
            if(StringUtils.isNotEmpty(orderGoods.getWxId())){
                customerUser.setWxId(orderGoods.getWxId());
            }
            // 扣减客户的金额
            customerUser.setBalance(customerUser.getBalance().subtract(orderGoods.getActualAmount()));
            orderGoods.setPayStatus(UserConstants.PAY_STATUS_PAID);
            orderGoodsMapper.insertOrderGoods(orderGoods);
            customerUserService.updateUserMoney(customerUser);
            finishPay(orderGoods);
        }else if(orderGoods.getPayType().equals(UserConstants.PAY_TYPE_WX_OFFICIAL_ACCOUNT)){
            // 使用微信公众号支付
            orderGoodsMapper.insertOrderGoods(orderGoods);
            // 使用微信公众号支付
            CustomerUser cu = customerUserService.selectUserById(userId);
            BigDecimal yibai = new BigDecimal("100");
            float actualAmount = orderGoods.getActualAmount().multiply(yibai).intValue();
            // totalFee 必须要以分为单位
            Object createOrderResult = bizWechatPayService.createOrder("服务下单", orderNo, (int) actualAmount,
                    cu.getOpenId(), UserConstants.PAY_TYPE_WX_OFFICIAL_ACCOUNT, UserConstants.FINANCE_ORDER, orderGoods.getShopId());
            orderGoods.setPayParams(createOrderResult);
        }
        return orderGoods;
    }

    @Override
    // 完成支付，发送通知
    public void finishPay(OrderGoods orderGoods){
        // 客户新增财务记录
        customerFinanceCenter(orderGoods, UserConstants.FINANCE_ORDER);
        // 微信通知
        wxOAuthchatService.messageOrderPaySuccess(orderGoods.getOrderNo());
    }

    /**
     * 完成商品订单信息
     *
     * @param orderNo 商品订单信息
     * @return 结果
     */
    @Override
    @Transactional
    public AjaxResult finishOrderGoods(String orderNo)
    {
        OrderGoods order = orderGoodsMapper.selectOrderGoodsByOrderNo(orderNo);
        if(StringUtils.isNull(order)){
            return AjaxResult.error("操作失败：订单不存在");
        }
        if(!order.getStatus().equals(UserConstants.STATUS_IN)){
            return AjaxResult.error("操作失败：订单状态不支持更改");
        }
        order.setStatus(UserConstants.STATUS_FINISH);
        order.setEndTime(new Date());
        // 结算
        settleCenter(order);
        orderGoodsMapper.updateOrderGoods(order);
        return AjaxResult.success(order);
    }

    /**
     * 取消商品订单信息
     *
     * @param orderGoods 商品订单信息
     * @return 结果
     */
    @Override
    @Transactional
    public int cancelOrderGoods(OrderGoods orderGoods)
    {
        ConfigOrder configOrder = configOrderService.selectConfigOrderByShopId(orderGoods.getShopId());
        if(orderGoods.getPayType().equals(UserConstants.PAY_TYPE_WX_OFFICIAL_ACCOUNT) &&
                configOrder.getStatusRefund().equals(UserConstants.YES)){
            // 微信公众号支付
            BigDecimal yibai = new BigDecimal("100");
            float totalFee = orderGoods.getActualAmount().multiply(yibai).intValue();
            // 开启原路退回
            bizWechatPayService.wxRefund(orderGoods.getOrderNo(), (int) totalFee, orderGoods.getPayType(),
                    UserConstants.FINANCE_ORDER, orderGoods.getShopId());
        }else{
            CustomerUser customerUser = customerUserService.selectUserById(orderGoods.getOrderUserId());
            // 增加客户的余额
            customerUser.setBalance(customerUser.getBalance().add(orderGoods.getActualAmount()));
            customerUserService.updateUserMoney(customerUser);
            orderGoods.setStatus(UserConstants.STATUS_CANCEL);
            orderGoods.setPayStatus(UserConstants.PAY_STATUS_REFUND_WALLET);
        }

        customerFinanceCenter(orderGoods, UserConstants.FINANCE_BACK);

        String reason = "未知原因";
        // 取消原因 （customer-客户主动取消 employee-店员主动取消 system-后台取消 overtime-超时未结单取消
        if(orderGoods.getCancelType().equals("customer")){
            reason = "客户主动取消";
        }else if(orderGoods.getCancelType().equals("employee")){
            reason = "店员主动取消";
        }else if(orderGoods.getCancelType().equals("system")){
            reason = "后台取消";
        }else if(orderGoods.getCancelType().equals("overtime")){
            reason = "超时未接单取消";
        }
        orderGoods.setOvertimeCancelTime(new Date());
        orderGoods.setIsOvertimeCancel(UserConstants.YES);
        // 微信通知 - 取消订单
        wxOAuthchatService.messageOrderPayCancel(orderGoods.getOrderNo(), reason);

        return orderGoodsMapper.updateOrderGoods(orderGoods);
    }

    // 订单超时提醒
    @Override
    public void updateOrderGoodsOvertimeNotice()
    {
        OrderGoods orderGoods = new OrderGoods();
        orderGoods.setIsAccept(UserConstants.YES); // 已接受
        orderGoods.setIsOvertimeNotice(UserConstants.NO);   // 未提醒过
        orderGoods.setPayStatus(UserConstants.PAY_STATUS_PAID); // 已支付
        Map<String, Object> map = new HashMap<>();
        map.put("overtimeNoticeTime", "overtimeNoticeTime"); // 当前时间大于订单设置的订单超时时间
        orderGoods.setParams(map);
        List<OrderGoods> list = orderGoodsMapper.selectOrderGoodsList(orderGoods);
        // 微信通知 - 订单超时提醒
        for(OrderGoods og : list){
            og.setIsOvertimeNotice(UserConstants.YES);
            orderGoodsMapper.updateOrderGoods(og);
            // 微信通知 - 超时提醒
            wxOAuthchatService.messageOrderOvertime(og.getOrderNo());
        }
    }

    // 订单超时取消
    @Override
    public void updateOrderGoodsOvertimeCancel()
    {
        OrderGoods orderGoods = new OrderGoods();
        orderGoods.setPayStatus(UserConstants.PAY_STATUS_PAID); // 已支付
        orderGoods.setIsOvertimeCancel(UserConstants.NO);   // 未取消过
        Map<String, Object> map = new HashMap<>();
        map.put("overtimeCancelTime", "overtimeCancelTime"); // 当前时间大于订单设置的订单取消时间
        orderGoods.setParams(map);
        List<OrderGoods> list = orderGoodsMapper.selectOrderGoodsList(orderGoods);
        // 微信通知 - 订单超时取消
        for(OrderGoods og : list){
            og.setCancelType("overtime");
            cancelOrderGoods(og);
        }
    }

    /**
     * 修改保存商品订单信息
     * 
     * @param orderGoods 商品订单信息
     * @return 结果
     */
    @Override
    @Transactional
    public int updateOrderGoods(OrderGoods orderGoods)
    {
        return orderGoodsMapper.updateOrderGoods(orderGoods);
    }

    /**
     * 修改商品订单状态
     * 
     * @param orderGoods 商品订单信息
     * @return 结果
     */
    @Override
    public int updateOrderGoodsStatus(OrderGoods orderGoods)
    {
        return orderGoodsMapper.updateOrderGoods(orderGoods);
    }

    /**
     * 修改商品订单评价状态
     *
     * @param orderGoods 商品订单信息
     * @return 结果
     */
    @Override
    public int updateOrderGoodsIsRate(OrderGoods orderGoods)
    {
        return orderGoodsMapper.updateOrderGoods(orderGoods);
    }

    /**
     * 修改商品订单支付状态
     *
     * @param orderGoods 商品订单信息
     * @return 结果
     */
    @Override
    public int updateOrderGoodsPayStatus(OrderGoods orderGoods)
    {
        return orderGoodsMapper.updateOrderGoods(orderGoods);
    }

    /**
     * 修改商品订单接单状态
     *
     * @param orderGoods 商品订单信息
     * @return 结果
     */
    @Override
    public int updateOrderGoodsIsAccept(OrderGoods orderGoods)
    {
        return orderGoodsMapper.updateOrderGoods(orderGoods);
    }

    /**
     * 通过商品订单编号删除商品订单
     * 
     * @param orderNo 商品订单编号
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteOrderGoodsByOrderNo(String orderNo)
    {
        return orderGoodsMapper.deleteOrderGoodsByOrderNo(orderNo);
    }

    /**
     * 批量删除商品订单信息
     * 
     * @param orderNos 需要删除的商品订单编号
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteOrderGoodsByOrderNos(String[] orderNos)
    {
        return orderGoodsMapper.deleteOrderGoodsByOrderNos(orderNos);
    }

    @Override
    // 客户财务记录
    public void customerFinanceCenter(OrderGoods orderGoods, String financeType){
        // 客户财务
        CustomerFinance customerFinance = new CustomerFinance();
        customerFinance.setUserId(orderGoods.getOrderUserId());
        customerFinance.setFinanceType(financeType);
        customerFinance.setOrderNo(orderGoods.getOrderNo());
        customerFinance.setAmount(orderGoods.getActualAmount());
        customerFinance.setShopId(orderGoods.getShopId());
        customerFinanceService.insertCustomerFinance(customerFinance);

        // 不是退款
        if(!financeType.equals(UserConstants.FINANCE_BACK)){
            // 客户数据统计
            customerStaticService.updateUserOrder(orderGoods.getOrderUserId(), orderGoods.getActualAmount());
        }
    }

    // 店员财务记录
    public void employeeFinanceCenter(OrderGoods orderGoods, String financeType){
        // 店员财务
        EmployeeFinance employeeFinance = new EmployeeFinance();
        employeeFinance.setUserId(orderGoods.getEmployeeUserId());
        employeeFinance.setFinanceType(financeType);
        employeeFinance.setOrderNo(orderGoods.getOrderNo());
        employeeFinance.setAmount(orderGoods.getEmployeeGetAmount());
        employeeFinance.setShopId(orderGoods.getShopId());
        employeeFinanceService.insertEmployeeFinance(employeeFinance);
    }

    // 结算中心
    public void settleCenter(OrderGoods orderGoods){

        CustomerUser customerUser = customerUserService.selectUserById(orderGoods.getOrderUserId());

        // 店员提成比例
        int rate = 1; // 比例
        Map<String, Object> map = new HashMap<>();
        map.put("orderUserId", orderGoods.getOrderUserId());
        map.put("employeeUserId", orderGoods.getEmployeeUserId());
        EmployeeUser employeeUser = employeeUserService.selectUserById(orderGoods.getEmployeeUserId());
        Level level = levelService.selectLevelById(employeeUser.getUserLevel());
        int count = orderGoodsMapper.selectOrderGoodsCountTotal(orderGoods);
        if(count > 1){
            // 续单
            rate = level.getContinueOrderCommissionRate();
        }else{
            // 首单
            rate = level.getFirstOrderCommissionRate();
        }
        // 店员实际获得金额
        BigDecimal employeeGetMoney = orderGoods.getInitAmount().multiply(new BigDecimal(rate)).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
        orderGoods.setEmployeeGetAmount(employeeGetMoney);
        orderGoods.setFinalAmount(orderGoods.getInitAmount().subtract(employeeGetMoney));

        // 有邀请用户 - 该邀请用户是否分销
        if(StringUtils.isNotNull(customerUser.getInviteId())){
            CustomerDistribution customerDistribution = customerDistributionService.selectUserById(customerUser.getInviteId());
            // 有邀请用户，并且是分销者，并且状态正常 且分销模式是提成CPS
            if(StringUtils.isNotNull(customerDistribution) && customerDistribution.getActive().equals(UserConstants.ZERO) && customerDistribution.getDistributionModel().equals(UserConstants.CPS)){
                customerDistributionService.updateUserOrder(customerDistribution, orderGoods.getInitAmount());
                // 订单设置分销员
                orderGoods.setDistributionUserId(customerUser.getInviteId());
                orderGoods.setIsDistribution(UserConstants.YES);

                // 设置舍入模式，这里使用四舍五入，并保留两位小数  获得的收益
                BigDecimal distributionAmount = orderGoods.getInitAmount().multiply(new BigDecimal(customerDistribution.getDistributionRate())).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
                // 分销用户设置分销金额
                orderGoods.setDistributionAmount(distributionAmount);
                orderGoods.setFinalAmount(orderGoods.getInitAmount().subtract(distributionAmount.add(employeeGetMoney)));
            }
        }
        // 订单更改
        orderGoodsMapper.updateOrderGoods(orderGoods);
        // 店员财务记录
        employeeFinanceCenter(orderGoods, UserConstants.FINANCE_ORDER);
        // 店员数据埋点统计
        employeeStaticService.updateUserOrder(orderGoods.getEmployeeUserId(), orderGoods.getEmployeeGetAmount());
    }
}
